﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;

namespace Fadd.Components.Tests
{
	public class ComponentManagerTest
	{
		private readonly ComponentManager _manager = new ComponentManager();

		[Fact]
		private void TestCreateCircular()
		{
			_manager.Add<CircularA, CircularA>();
			_manager.Add<CircularC, CircularC>();
			_manager.Add<CircularB, CircularB>();
			Assert.Throws(typeof (CircularDependenciesException), () => _manager.CreateAll());

			try
			{
				_manager.CreateAll();
			}
			catch (CircularDependenciesException err)
			{
				Assert.Equal(3, err.Components.Count);
				Assert.Equal("CircularA", err.Components[0].InstanceType.Name);
				Assert.Equal("CircularB", err.Components[1].InstanceType.Name);
				Assert.Equal("CircularC", err.Components[2].InstanceType.Name);
			}
		}

		[Fact]
		private void TestValidateCircular()
		{
			_manager.Add<CircularA, CircularA>();
			_manager.Add<CircularC, CircularC>();
			_manager.Add<CircularB, CircularB>();
			Assert.Throws(typeof(CircularDependenciesException), () => _manager.ValidateAll());

			try
			{
				_manager.ValidateAll();
			}
			catch (CircularDependenciesException err)
			{
				Assert.Equal(3, err.Components.Count);
				Assert.Equal("CircularA", err.Components[0].InstanceType.Name);
				Assert.Equal("CircularB", err.Components[1].InstanceType.Name);
				Assert.Equal("CircularC", err.Components[2].InstanceType.Name);
			}
		}

		[Fact]
		private void CreateSingleComponent()
		{
			_manager.Add<IComponentA, ComponentA>();
			Assert.IsType(typeof(ComponentA), _manager.Get<IComponentA>());
		}

		[Fact]
		private void NoExistingComponent()
		{
			Assert.Null(_manager.Get<IComponentB>());
		}

		[Fact]
		private void MissingParameter()
		{
			_manager.Add<MissingArgument, MissingArgument>();
			Assert.Throws(typeof (ConstructorMismatchException), () => _manager.CreateAll());
		}

		[Fact]
		private void CustomParameter()
		{
			_manager.Add<MissingArgument, MissingArgument>();
			_manager.AddParameters(typeof (MissingArgument), "hostName", "www.gauffin.com", "port", 80);
			Assert.IsType(typeof(MissingArgument), _manager.Get<MissingArgument>());
		}

		[Fact]
		private void ParameterEvent()
		{
			_manager.ParameterRequested += OnGetParameter;
			_manager.Add<MissingArgument, MissingArgument>();
			Assert.IsType(typeof(MissingArgument), _manager.Get<MissingArgument>());
		}

		[Fact]
		private void DifferentVersions()
		{
			_manager.Add<IVersionComponent, Version1>();
			_manager.Add<IVersionComponent, Version2>();
			Assert.IsType(typeof (Version2), _manager.Get<IVersionComponent>());
		}

		private void OnGetParameter(object sender, ParameterRequestedEventArgs e)
		{
			switch (e.ParameterName)
			{
				case "hostName":
					e.ParameterValue = "www.gauffin.com";
					break;
				case "port":
					e.ParameterValue = 80;
					break;
			}

		}
	}
}
